from windoh.control import Control


class Root(Control):

    class WindowDispatcher(object):
        def __init__(self, root):
            self.root = root

        def on_mouse_press(self, *args):
            self.root.dispatch_mouse_event('on_mouse_press', *args)

        def on_mouse_release(self, *args):
            if self.root._dragging is not None:
                self.root.dispatch_event('on_stop_drag', self.root._dragging)
            else:
                self.root.dispatch_mouse_event('on_mouse_release', *args)

        def on_mouse_motion(self, *args):
            self.root.dispatch_mouse_event('on_mouse_motion', *args)

        def on_mouse_drag(self, *args):
            if self.root._dragging is not None:
                self.root._dragging.dispatch_event('on_drag', *args)
            else:
                self.root.dispatch_mouse_event('on_mouse_motion', *args[:4])
            #    self.root.dispatch_mouse_event('on_mouse_drag', *args)

        def on_resize(self, width, height):
            self.root.dispatch_event('on_resize', width, height)

        def on_key_press(self, *args):
            if self.root._focused is not None:
                self.root._focused.dispatch_event('on_key_press', *args)
            else:
                self.root.dispatch_event('on_key_press', *args)

        def on_key_release(self, *args):
            if self.root._focused is not None:
                self.root._focused.dispatch_event('on_key_release', *args)
            else:
                self.root.dispatch_event('on_key_release', *args)

        def on_text(self, text):
            if self.root._focused is not None:
                self.root._focused.dispatch_event('on_text', text)
            else:
                self.root.dispatch_event('on_text', text)


    def __init__(self, window, renderer, style, cursors=None, **kwargs):
        if not kwargs.has_key('width'):
            kwargs['width'] = window.width
        if not kwargs.has_key('height'):
            kwargs['height'] = window.height
        if not kwargs.has_key('left'):
            kwargs['left'] = 0
        if not kwargs.has_key('bottom'):
            kwargs['bottom'] = 0
        Control.__init__(self, **kwargs)

        self._window = window
        self._renderer = renderer
        self._focused = None
        self._dragging = None
        self._hovered = None
        self._root = self
        self._base_style = style

        style.push_handlers(on_style_change=self.on_base_style_change)

        window.push_handlers(self.WindowDispatcher(self))

        self._cursor = None

        if cursors is None:
            cursors = {
                'default': window.CURSOR_DEFAULT,
                'hand': window.CURSOR_HAND,
                'size': window.CURSOR_SIZE,
                'size_down_left': window.CURSOR_SIZE_DOWN_LEFT,
                'size_down_right': window.CURSOR_SIZE_DOWN_RIGHT,
                'size_up_left': window.CURSOR_SIZE_UP_LEFT,
                'size_up_right': window.CURSOR_SIZE_UP_RIGHT,
                'text': window.CURSOR_TEXT,
            }

            self._cursors = {}
            for k, v in cursors.iteritems():
                self._cursors[k] = window.get_system_mouse_cursor(v)
        else:
            self._cursors = cursors

    #def on_child_append(self, child):
    #    child.root = self
    #    if child._renderer is None:
    #        child._renderer = self._renderer

    def on_resize(self, width, height):
        self.style.update(dict(width=width, height=height))

    def on_focus_changed(self, control):
        if self._focused is control:
            return
        if self._focused is not None:
            self._focused.dispatch_event('on_blur')
        self._focused = control
        control.dispatch_event('on_focus')

    def on_focus_lost(self, control):
        if self._focused is not control:
            return
        self.on_focus_changed(None)

    def on_start_drag(self, control):
        assert(self._dragging is None)
        print "start drag", control
        self._dragging = control
        control.dispatch_event('on_start_drag')
        
    def on_stop_drag(self, control):
        assert(self._dragging is control)
        print "stop drag", control
        control.dispatch_event('on_stop_drag')
        self._dragging = None

    def on_mouse_over(self, control=None):
        if control is None:
            return Control.on_mouse_over(self)
        if control is self._hovered:
            return 
        if self._hovered is not None:
            self._hovered.dispatch_event('on_mouse_out')
        self._hovered = control
        if control is not None:
            control.dispatch_event('on_mouse_over')

    def set_cursor(self, cursor='default'):
        if self._cursor != cursor:
            self._cursor = cursor
            self._window.set_mouse_cursor(self._cursors[cursor])

    def on_base_style_change(self, attrs):
        self._renderer.all_dirty = True


Root.register_event_type('on_focus_changed')
Root.register_event_type('on_focus_lost')
Root.register_event_type('on_resize')
#Root.register_event_type('on_start_drag')
#Root.register_event_type('on_stop_drag')


